﻿using Microsoft.AspNetCore.WebUtilities;
using System;
using System.Collections.Generic;

namespace Microsoft.AspNetCore.Authentication.Cookies
{
    /// <summary>
    /// CookieAuthenticationOptions 扩展类
    /// </summary>
    public static class CookieAuthenticationOptionsExtensions
    {
        /// <summary>
        /// 重写OnRedirectToLogin/OnRedirectToAccessDenied方法
        /// </summary>
        /// <param name="options">CookieAuthenticationOptions 实例</param>
        /// <param name="authHost">授权网站主机头</param>
        /// <param name="appId">当前应用程序 AppCode</param>
        /// <param name="loginPath">登录地址，默认为 CookieAuthenticationDefaults.LoginPath</param>
        /// <param name="accessDeniedPath">拒绝访问地址，默认为 CookieAuthenticationDefaults.AccessDeniedPath</param>
        public static void RebuildRedirectUri(this CookieAuthenticationOptions options, string authHost, string appId = "0", string loginPath = null, string accessDeniedPath = null)
        {
            var originRedirectToLogin = options.Events.OnRedirectToLogin;
            options.Events.OnRedirectToLogin = context =>
            {
                return originRedirectToLogin(context.RebuildRedirectUri(authHost, appId, loginPath ?? CookieAuthenticationDefaults.LoginPath.Value));
            };

            var originRedirectToAccessDenied = options.Events.OnRedirectToAccessDenied;
            options.Events.OnRedirectToAccessDenied = context =>
            {
                return originRedirectToAccessDenied(context.RebuildRedirectUri(authHost, appId, accessDeniedPath ?? CookieAuthenticationDefaults.AccessDeniedPath));
            };
        }

        private static RedirectContext<CookieAuthenticationOptions> RebuildRedirectUri(this RedirectContext<CookieAuthenticationOptions> context, string authHost, string appId, string url)
        {
            if (context.RedirectUri.StartsWith(authHost)) return context;

            var uriBuilder = new UriBuilder(authHost);
            uriBuilder.Path = uriBuilder.Path.TrimEnd('/') + url;
            context.RedirectUri = RebuildUriQuery(context, uriBuilder, appId);
            return context;
        }

        private static string RebuildUriQuery(RedirectContext<CookieAuthenticationOptions> context, UriBuilder uriBuilder, string appId)
        {
            // 获得原始认证地址 http://localhost:49185/Account/Login?ReturnUrl=%2FHome%2FAbout%3FTest1%3D1%26Test2%3D2
            var originUri = new Uri(context.RedirectUri);
            var queryStrings = QueryHelpers.ParseQuery(originUri.Query);

            // 新返回地址 http://localhost:49185/Home/About?Test1=1&Test2=2
            var returnUrl = originUri.GetComponents(UriComponents.SchemeAndServer, UriFormat.Unescaped) + queryStrings[context.Options.ReturnUrlParameter];

            // 拼装新的认证地址 http://localhost:50852/Account/Login?ReturnUrl=http%3A%2F%2Flocalhost%3A49185%2FHome%2FAbout%3FTest1%3D1%26Test2%3D2&AppId=2
            var querys = new Dictionary<string, string>();
            querys.Add(context.Options.ReturnUrlParameter, returnUrl);
            querys.Add("AppId", appId);
            return QueryHelpers.AddQueryString(uriBuilder.ToString(), querys);
        }
    }
}
